/*
 * DbAccess.cpp
 *
 *  Created on: Jan 28, 2013
 *      Author: root
 */

#include "DbAccess.h"

/*
 * sql define
 * create connecton table,and table index
 * flag:failure 0, success 1
 * status:session live AUTH_WAIT 0->1,AUTH completed 2,AUTH_DISCONN_WAIT 3->4,AUTH_DISCONN completed 5
 * */
static const char * create_vod_connection_table_sql = "CREATE TABLE  vodconnections (   \n"
    "  id INTEGER PRIMARY KEY, \n"
    "  Node_Id       INTEGER default 0,  \n"
    "  Conn_Id       INTEGER default 0,  \n"
    "  CleintIP      VARCHAR(64) default '127.0.0.1',  \n"
    "  SessionId     VARCHAR(128) default '0' ,  \n"
    "  File_Name     TEXT ,  \n"
    "  Url           TEXT,   \n"
	"  Total_KB      BIGINT default 0,   \n"
	"  Total_Secs    INTEGER default 0,  \n"
	"  CreatDateTime DATETIME  default CURRENT_TIMESTAMP,  \n"
	"  SessionBeginTime   BIGINT  default 0, \n"
	"  SessionEndTime     BIGINT  default 0, \n"
	"  flag          INTEGER  default 0, \n"
	"  status        INTEGER  default 0)";
/*
 * sql define
 * create connecton table index
 * */
static const char * create_vod_connection_index = "create index session_index on vodconnections(SessionId)";

/**
 * DbAccess class
 */
DbAccess::DbAccess() {
	memset(this->dbsvr,'\0',sizeof(this->dbsvr));
	this->open_flag = 0;
	pSvrlog = NULL;
}

/**
 * DbAccess class free
 */
DbAccess::~DbAccess() {
	/*
	 * add your code here
	 */
}

/**
 * init db access operation buf
 */
int DbAccess::init(const char * dbpath,Svr_log * psvrlog)
{
    if(dbpath == NULL)
        return FAILURE;

    const char * ptr  = NULL;
    ptr = strstr(dbpath,".db");
    if(ptr != NULL)
    {
        strcpy(this->dbsvr,dbpath);
    }

    /*init pool*/
    table_pool_lock.Lock();
    {
        for(int i = 0;i < 16 ;i++)
        {
            vodconnection * row = new vodconnection();
            if(row != NULL)
            {
                free_table_pool.push(row);
            }
        }

        table_pool_lock.Unlock();
    }

    /**
     * log
     */
    this->pSvrlog = psvrlog;

    return SUCCESS;
}

/**
 * create and init db
 */
int DbAccess::create_db()
{
	int ret = -1;

	ret = db_sqlite_exec(create_vod_connection_table_sql);

	/*
	 * create table index
	 */
	if(ret == 200)
	{
		db_sqlite_exec(create_vod_connection_index);
	}

	return ret;
}

int DbAccess::connectodb()
{
    int ret = -1;
    /*lock*/
    dblock.Lock();
    {
        if(open_flag == 0)
        {
			/*check db is exist,and init database*/
			if(access(dbsvr,F_OK) != 0)
			{
				ret = create_db();
			}
			else
			{
				/*check is have connection table*/
				create_db();

				/*end*/
				ret = 200;
			}

            /*check connection status*/
            if(ret == 200)
            {
                open_flag = 1;
            }
        }
        else
        {
            /**do nothing**/
            ret = 200;
        }

        /*unlock*/
        dblock.Unlock();
    }

    return ret;
}

int DbAccess::execnosql(const char * sqlstr)
{
    int ret = -1;
    if(open_flag == 0 || sqlstr == NULL  || strlen(sqlstr) == 0)
        return ret;

    /*lock*/
    dblock.Lock();
    {
        /*open db connect*/
        ret = db_sqlite_exec(sqlstr);

        dblock.Unlock();
    }

    return ret;
}

int DbAccess::querryvodconnection(const char * sqlstr,vodconnection * pRow)
{
      int ret = -1;
      if(open_flag == 0 || sqlstr == NULL  || strlen(sqlstr) == 0 || pRow == NULL)
          return ret;

      /*lock*/
      dblock.Lock();
      {
          /*open db connect*/
          ret = db_sqlite_querry_vodconnection(sqlstr,pRow);

          dblock.Unlock();
      }

      return ret;
}

int DbAccess::db_sqlite_exec(const char * sqlstr)
{
     int ret = -1;
     sqlite3 *db = NULL;
     ret = sqlite3_open(dbsvr, &db);
     if (ret !=  SQLITE_OK || db == NULL)
     {
          this->pSvrlog->log_fmt(LOG_ERR,"Could not open database: %d,%s\n",ret,sqlite3_errmsg(db));
          ret = 403;
          sqlite3_close(db);
     }
     else
     {
          ret = sqlite3_exec(db,sqlstr,NULL,NULL,NULL);
          if (ret != SQLITE_OK)
          {
        	  this->pSvrlog->log_fmt(LOG_ERR,"SQL error: %s\n sql:%s\n", sqlite3_errmsg(db),sqlstr);
              ret = 503;
          }
          else
          {
              ret = 200;
          }

          /*close db*/
          sqlite3_close(db);
     }

     return ret;
}

int DbAccess::db_sqlite_querry_vodconnection(const char * sqlstr,vodconnection * pRow)
{
     int ret = -1;
     sqlite3 *db = NULL;
     ret = sqlite3_open(dbsvr, &db);
     if (ret !=  SQLITE_OK || db == NULL)
     {
    	  this->pSvrlog->log_fmt(LOG_ERR,"Could not open database: %d,%s\n", ret,sqlite3_errmsg(db));
          ret = 403;
          sqlite3_close(db);
     }
     else
     {
         sqlite3_stmt *stmt;
         ret= sqlite3_prepare(db,sqlstr, strlen(sqlstr), &stmt,0);
         if (ret != SQLITE_OK)
         {
        	  this->pSvrlog->log_fmt(LOG_ERR,"Can't open statement: %s/n", sqlite3_errmsg(db));
              ret =  503;
         }
         else
         {
				char * CleintIP = NULL;
				char * SessionId = NULL;
				char * filename = NULL;
				char * url = NULL;
				char * Create_Time = NULL;

				while(sqlite3_step(stmt) == SQLITE_ROW )
				{
					  pRow->id = sqlite3_column_int(stmt, 0);
					  pRow->Node_Id = sqlite3_column_int(stmt, 1);
					  pRow->Conn_Id  = sqlite3_column_int(stmt, 2);

					  CleintIP = (char *)sqlite3_column_text(stmt,3);
					  if(CleintIP != NULL && (strlen(CleintIP) < sizeof(pRow->CleintIP)))
						  strcpy(pRow->CleintIP,CleintIP);

					  SessionId = (char *)sqlite3_column_text(stmt,4);
					  if(SessionId != NULL && (strlen(SessionId) < sizeof(pRow->SessionId)))
						  strcpy(pRow->SessionId,SessionId);

					  filename = (char *)sqlite3_column_text(stmt,5);
					  if(filename != NULL && (strlen(filename) < sizeof(pRow->File_Name)))
						  strcpy(pRow->File_Name,filename);

					  url = (char *)sqlite3_column_text(stmt,6);
					  if(url != NULL && (strlen(url) < sizeof(pRow->Url)))
						  strcpy(pRow->Url,url);

					  pRow->Total_KB  = sqlite3_column_int64(stmt,7);
					  pRow->Total_Secs =  sqlite3_column_int(stmt,8);

					  Create_Time = (char *)sqlite3_column_text(stmt,9);
					  if(Create_Time != NULL && (strlen(Create_Time) < sizeof(pRow->CreatDateTime)))
						  strcpy(pRow->CreatDateTime,Create_Time);

					  pRow->SessionBeginTime  = (long)sqlite3_column_int64(stmt,10);
					  pRow->SessionEndTime  = (long)sqlite3_column_int64(stmt,11);
					  pRow->flag =  sqlite3_column_int(stmt,12);
					  pRow->status =  sqlite3_column_int(stmt,13);

					  pRow->fit_flag = 1;

					  /*only one recorder*/
					  ret = 200;
					  break;
				}

			   /*free*/
			   sqlite3_finalize(stmt);
         }

         /*close db*/
         sqlite3_close(db);
     }

     return ret;
}

/**
 * alloc_vodconnection_row_buf
 */
int DbAccess::alloc_vodconnection_row_buf(vodconnection ** pRow)
{
    if(pRow == NULL || (*pRow) != NULL)
        return -1;
    table_pool_lock.Lock();
    {
          if(this->free_table_pool.size() > 0)
          {
              *pRow = free_table_pool.top();
              free_table_pool.pop();
          }
          else
          {
              *pRow = new vodconnection();
          }
          table_pool_lock.Unlock();
    }

    return SUCCESS;
}

/**
 * reset_vodconnection_row_buf
 */
void DbAccess::reset_vodconnection_row_buf(vodconnection * pRow)
{
    if(pRow == NULL)
       return ;

    pRow->id = 0;
    pRow->Node_Id = 0;
    pRow->Conn_Id = 0;
	memset(pRow->CleintIP,'\0',sizeof(pRow->CleintIP));
	memset(pRow->SessionId,'\0',sizeof(pRow->SessionId));
	memset(pRow->File_Name,'\0',sizeof(pRow->File_Name));
	memset(pRow->Url,'\0',sizeof(pRow->Url));
	pRow->Total_KB = 0;
	pRow->Total_Secs = 0;
	memset(pRow->CreatDateTime,'\0',sizeof(pRow->CreatDateTime));
	pRow->SessionBeginTime = 0;
	pRow->SessionEndTime = 0;
	pRow->flag = 0;
	pRow->status = 0;

	/**
	* fit_flag:1,means struct data has been seted.
	*/
	pRow->fit_flag = 0;
}

/**
 * free_vodconnection_row_buf
 */
void DbAccess::free_vodconnection_row_buf(vodconnection * pRow)
{
    if(pRow == NULL)
        return ;
    /**
     * reset
     */
    reset_vodconnection_row_buf(pRow);

    table_pool_lock.Lock();
    {
        this->free_table_pool.push(pRow);

        table_pool_lock.Unlock();
    }
}
